home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
Sherlock 2.0
/
DevLibSrc
/
Main_DevLib
/
LIBofile.h
< prev
next >
Wrap
Text File
|
1995-02-08
|
10KB
|
314 lines
/*
devlib: Header describing the format of the object file.
Warning: changes to this file affect both the AS and the LINK applications.
source: LIBofile.h
started: May 9, 1994.
version:
February 3, 1995.
Added comment nodes.
Added f_area_comments field to areas.
Removed f_ref_next field.
Added LAST_REF bit and related macros.
May 21, 1994.
Added abbreviations for byte nodes.
May 19, 1994.
Added f_unit_name.
May 13, 1994.
Added f_area_index.
May 12, 1994.
Added f_area_name.
Added fh_areas.
May 11, 1994.
Area nodes now contain reference lists.
May 9, 1994.
All flags are shared between in-memory and file versions.
*/
#ifndef LIBofile_h_
#define LIBofile_h_
#pragma once
/*
Define abbreviations.
*/
#define f_comment_ptr(p)((f_comment *) (p))
#define f_header_ptr(p) ((f_header *) (p))
#define f_ref_ptr(p) ((f_ref_node *) (p))
#define f_tail_ptr(p) ((f_trailer *) (p))
/*
Define the typedefs of the object file.
An offset is the number of bytes from the start of an object file.
Offsets are converted to pointers by the fscan routines.
A zero offset represents a NULL pointer.
An index is a position relative to some (understood) data structure.
Zero is *not* a valid index and represents an end-of-list.
*/
typedef ulong f_offset;
typedef ulong f_index;
typedef struct f_area_node_struct f_area_node;
typedef struct f_comment_struct f_comment;
typedef struct f_dict_node_struct f_dict_node;
typedef struct f_header_struct f_header;
typedef struct f_ref_node_struct f_ref_node;
typedef struct f_trailer_struct f_trailer;
typedef struct f_unit_node_struct f_unit_node;
/*
An area consists of an ordered sequence of bits, specified by a byte list.
2/3/95: added f_area_comments field.
*/
static struct f_area_node_struct {
f_index f_area_index; /* The file index. */
ulong f_area_app_length; /* Size of the area in the application. */
ulong f_area_file_length; /* Unpadded size of the area in the object file. */
f_offset f_area_refs; /* The references from within this area. */
f_offset f_area_bytes; /* The "byte list" of the area. */
f_offset f_area_comments; /* The comment list. */
f_index f_area_name; /* The dictionary index of the area's name. */
};
/*
The byte list represents the bytes of an area.
I'm unsure about whether to use a byte list,
so the byte list is used only if USE_BYTE_LIST is #defined.
The byte list handles larege DCB instructions more efficiently
and also allows the linker more flexibility in alignment.
fill nodes are generated from DCB instructions.
align nodes are generated from ALIGN instructions.
byte nodes are generated from all other cnodes.
byte nodes are followed by the indicated number of bytes.
*/
#undef USE_BYTE_LIST
#define USE_BYTE_LIST
#ifdef USE_BYTE_LIST
/* Abbreviations. */
#define f_align_ptr(p) ((f_align_node *) (p))
#define f_byte_ptr(p) ((f_byte_node *) (p))
#define f_fill_ptr(p) ((f_fill_node *) (p))
/* Define the type codes in byte nodes. */
enum { F_BAD_TYPE, F_ALIGN_TYPE, F_BYTE_TYPE, F_FILL_TYPE };
typedef struct f_align_node_struct f_align_node;
typedef struct f_byte_node_struct f_byte_node;
typedef struct f_fill_node_struct f_fill_node;
#define BYTE_NODE_HEAD\
short f_byte_type;\
f_offset f_byte_next
static struct f_align_node_struct {
BYTE_NODE_HEAD;
short f_align_pad;
};
static struct f_byte_node_struct {
BYTE_NODE_HEAD;
ulong f_byte_size;
};
static struct f_fill_node_struct {
BYTE_NODE_HEAD;
ulong f_fill_count;
long f_fill_val;
};
#endif
/*
The comment list contains all line and stack comments for an area.
The list is terminated with a node with a zero comment_kind.
*/
static struct f_comment_struct {
short f_comment_kind; /* C_xxx_COMMENT: see below. */
ulong f_comment_offset; /* Stack offset (location counter for line comments) */
ulong f_comment_size; /* Size of variable (not used for line comments) */
};
/* Define the possible values of f_comment_kind and comment_kind fields (AScnodes.h). */
enum {
C_BAD_COMMENT = 0,
C_AUTO_COMMENT,
C_BIG_TEMP_COMMENT,
C_FORMAL_COMMENT,
C_FTEMP_COMMENT,
C_HIDDEN_PTR_COMMENT,
C_LINE_COMMENT,
C_BAD_LAST_COMMENT
};
/*
The symbol dictionary contains one entry for each symbol defined or
referenced in the object file.
Each f_dict node is followed by the padded name of the symbol.
*/
static struct f_dict_node_struct {
f_index f_dict_area; /* The area in which the label is defined, or 0. */
f_offset f_dict_offset; /* Offset of the symbol from the start of the unit. */
short f_dict_length; /* The length of the *unpadded* symbol */
/* Dictionary flags are the same whether on disk or in memory. */
short dict_flags; /* Various flags defined below. */
};
/* Define operations on the dict_flag fields. */
enum {
DEF_DFLAG = 0x01, /* 1: the label is defined in this file. */
GLOBAL_DFLAG = 0x02, /* 1: the label is known outside this file. */
IMPORT_DFLAG = 0x04, /* 1: the label is imported from another file. */
REF_DFLAG = 0x08 /* 1: the label is referenced in this file. */
};
#define dict_is_defined(i) ((((i) -> dict_flags) & DEF_DFLAG) != 0)
#define dict_is_global(i) ((((i) -> dict_flags) & GLOBAL_DFLAG) != 0)
#define dict_is_imported(i) ((((i) -> dict_flags) & IMPORT_DFLAG) != 0)
#define dict_is_referenced(i) ((((i) -> dict_flags) & REF_DFLAG) != 0)
#define dict_set_defined(i) {(i) -> dict_flags |= DEF_DFLAG;}
#define dict_set_global(i) {(i) -> dict_flags |= GLOBAL_DFLAG;}
#define dict_set_import(i) {(i) -> dict_flags |= IMPORT_DFLAG;}
#define dict_set_referenced(i) {(i) -> dict_flags |= REF_DFLAG;}
/*
Object files start with a header.
The version and revision fields must exist in all object files.
The item field allows object files to have zero items.
The value of magic must match value in the end field in the trailer.
Headers, f_items and trailers are padded to a LINKER_PADDING boundary
using the padding macro defined below.
*/
#define LINK_VERSION 1 /* Development versions are less than 100. */
#define LINK_REVISION 2
#define MAX_REVISION 100
#define LINK_MAGIC 0x1234
#define LINKER_PADDING 2
#define padding(size) (size + ((LINKER_PADDING - (size % LINKER_PADDING)) % LINKER_PADDING))
static struct f_header_struct { /* Disk format... */
unsigned short fh_version; /* Version of the object file format. */
unsigned short fh_revision; /* Sub-version of the object file format. */
ulong fh_magic; /* Consistency check. */
ulong fh_reserved1; /* Reserved for future use. */
ulong fh_reserved2; /* Reserved for future use. */
ulong fh_symbols; /* The number of symbols in the symbol dictionary. */
ulong fh_units; /* The number of units in the file. */
ulong fh_areas; /* The number of areas in the file. */
f_offset fh_dictionary; /* Offset of the symbol dictionary or 0 if none. */
f_offset fh_unit; /* Offset of the first unit or 0 if none. */
};
/*
Each area contains a list of references contained within the area.
This list is used by the linker in two ways:
1) To determine what areas (hense what units) to link into the application.
2) To patch fields within included areas.
Associating ref nodes with areas instead of units allows
the linker to allocate code and data areas independently.
Reference nodes represent a reference to an atom of the indicated size.
WARNING:
We could get rid of the f_ref_next field by using a flag bit.
That would *not* be a good idea.
Although the f_ref_next wastes space in the .o file,
it *saves* main memory in the liner because the linker converts
f_ref_nodes to in-memory nodes in place!
*/
static struct f_ref_node_struct {
f_offset f_ref_next; /* Next node on the reference list. */
f_index f_ref_dict; /* Index of the label being referenced. */
ulong f_ref_offset; /* Bytes from start of area of the field to be patched. */
short f_ref_size; /* The size of the field to be patched, in bytes. */
/* Reference flags are the same whether on disk or in memory. */
short ref_flags; /* Attribute bits: see below */
};
/* Define bits in the ref_flags field. */
#define NEG_RFLAG 0x01
#define ref_set_neg(i) {(i) -> ref_flags |= NEG_RFLAG;}
#define ref_is_neg(i) ((((i) -> ref_flags) & NEG_RFLAG) != 0)
#if 0 /* Use a NULL f_ref_next field, not flag bits, to end the reference list! */
#define LAST_RFLAG 0x02
#define ref_set_last(i) {(i) -> ref_flags |= LAST_RFLAG;}
#define ref_is_last(i) ((((i) -> ref_flags) & LAST_RFLAG) != 0)
#endif
/*
The trailer field follows the last file item node.
This field exists solely as a consistency check on the file.
The assembler pads the file as necessary so that the trailer
starts on a LINKER_PADDING byte boundary.
*/
static struct f_trailer_struct {
ulong t_file_size; /* The file size, including the trailer. */
ulong t_end; /* Value of t_end must match value in h_magic. */
};
/*
A unit is the smallest element that can be included or excluded from an
application by the linker.
*/
static struct f_unit_node_struct {
f_offset f_unit_next; /* Offset of the next unit */
f_offset f_unit_code_area; /* Offset of the unit's code area. */
f_offset f_unit_data_area; /* Offset of the unit's data area. */
f_index f_unit_name; /* The dictionary index of the unit's name. */
/* Unit flags are the same whether on disk or in memory. */
short unit_flags; /* Various flags defined below. */
};
/*
Define abbreviations for operations on the m_unit_flag fields.
The SCAN_UFLAG field is used only by the linker.
*/
enum {
PROC_UFLAG = 0x01, /* TRUE: the unit is a PROC unit. */
RECORD_UFLAG = 0x02, /* TRUE: the unit is a RECORD unit. */
SCAN_UFLAG = 0x04 /* TRUE: the unit is on the scan list. */
};
#define unit_is_on_scan_list(i) ((((i) -> unit_flags) & SCAN_UFLAG) != 0)
#define unit_is_proc(i) ((((i) -> unit_flags) & PROC_UFLAG) != 0)
#define unit_is_record(i) ((((i) -> unit_flags) & RECORD_UFLAG) != 0)
#define unit_set_on_scan_list(i) { (i) -> unit_flags |= SCAN_UFLAG; }
#define unit_set_proc(i) { (i) -> unit_flags |= PROC_UFLAG; }
#define unit_set_record(i) { (i) -> unit_flags |= RECORD_UFLAG;}
#endif /* LIBofile_h_ */